package com.iwunu.auth.filter;

import com.iwunu.auth.config.JwtConfig;
import com.iwunu.auth.util.JwtTokenUtil;
import com.iwunu.auth.vo.JwtUserVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * JWT验证过滤器
 * @author kinfeng
 *
 */
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
	private static final Logger LOGGER = LoggerFactory.getLogger(JWTAuthenticationFilter.class);

	private JwtTokenUtil jwtTokenUtil;

	public JWTAuthenticationFilter(AuthenticationManager authenticationManager, JwtTokenUtil jwtTokenUtil) {
		super(authenticationManager);
		this.jwtTokenUtil = jwtTokenUtil;
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		JwtConfig jwtConfig = jwtTokenUtil.getJwtConfig();
		LOGGER.debug("get jwt header key:{}", jwtConfig.getHeaderKey());
		String authorization = request.getHeader(jwtConfig.getHeaderKey());

		if (authorization == null || !authorization.startsWith(jwtConfig.getHeaderPrefix())) {
//			LOGGER.info("jwt header authorization is empty, pass!");
			SecurityContextHolder.getContext().setAuthentication(null);
			chain.doFilter(request, response);
			return;
		}

		LOGGER.debug("jwt header {}:{}.", jwtConfig.getHeaderKey(), authorization);

		UsernamePasswordAuthenticationToken authentication = null;
		try {
			authentication = getAuthentication(authorization);
			LOGGER.debug("set security authentication:{}", jwtConfig.getHeaderKey());
			SecurityContextHolder.getContext().setAuthentication(authentication);

			String token = authorization.substring(jwtConfig.headerPrefixLength());
			JwtUserVo jwtUserVo = jwtTokenUtil.parse(token);
			if(jwtUserVo != null){
				response.addHeader("ID",jwtUserVo.getUsername());
			}

			chain.doFilter(request, response);
		} catch (Exception e) {
			e.printStackTrace();
			LOGGER.debug("jwt token invalid");
			response.setStatus(401);
			PrintWriter writer = response.getWriter();
			writer.println("{\n" +
					"  \"code\": -1,\n" +
					"  \"msg\": \"Invalid token\",\n" +
					"  \"data\": null\n" +
					"}");
		}
	}

	private UsernamePasswordAuthenticationToken getAuthentication(String authorization) {
		JwtConfig jwtConfig = jwtTokenUtil.getJwtConfig();
		String token = authorization.substring(jwtConfig.headerPrefixLength());

		JwtUserVo user = jwtTokenUtil.parse(token);

		return new UsernamePasswordAuthenticationToken(user.getUsername(), null, user.getAuthorities());
	}


}
